﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Opennav.MapGenerator.Map.POI;
using System.IO;
using Opennav.MapGenerator.Map.Labels;
using System.Diagnostics;
using Opennav.MapGenerator.Map.Locations;
using Opennav.MapGenerator.Geometry;

namespace Opennav.MapGenerator.Map.MapTiles
{
    public class MapPoint : MapObject
    {
        public static uint IS_POI = 0x80000000;

        private Coordinate _coordinate = null;

        public MapPoint(MapPointType type, Coordinate coordinate, Label label, int minResolution, int maxResolution)
            : base(minResolution, maxResolution)
        {
            this.Type = type;
            this._coordinate = coordinate;
            this.Label = label;
        }

        public MapPoint(MapPointType type, Coordinate coordinate, City city, int minResolution, int maxResolution)
            : base(minResolution, maxResolution)
        {
            this.Type = type;
            this._coordinate = coordinate;
            this.City = city;
        }

        public MapPoint(MapPoint src)
            : base(src.MinResolution, src.MaxResolution)
        {
            this.Type = src.Type;
            this.Label = src.Label;
            this.POI = src.POI;
            this.City = src.City;
            this._coordinate = src.Coordinate;
        }

        public MapPointType Type { get; private set; }

        public Label Label { get; private set; }

        public City City { get; private set; }

        public PointOfInterest POI { get; set; }

        public override Coordinate Coordinate
        {
            get
            {
                return _coordinate;
            }
        }

        public override void Write(Stream stream, MapTile tile, bool last)
        {
            BinaryWriter writer = new BinaryWriter(stream);
            ushort type = (ushort)(POINT | (0xfff & (int)this.Type));
            if (POI != null || Label != null || City != null) type = (ushort)(type | HAS_REF);
            if (last) 
                type = (ushort)(type | LAST_MAPOBJECT_FLAG);
            writer.Write(type);
            if (POI != null)
                writer.Write((uint)(IS_POI | (uint)(POI.Offset & 0x7fffffff)));
            else if (Label != null)
                writer.Write((uint)(Label.Offset & 0x7fffffff));
            else if (City != null)
                writer.Write((uint)(City.Label.Offset & 0x7fffffff));
            int deltaLon = (Coordinate.Longitude >> tile.Zoom.Shift) - (tile.Center.Longitude >> tile.Zoom.Shift);
            int deltaLat = (Coordinate.Latitude >> tile.Zoom.Shift) - (tile.Center.Latitude >> tile.Zoom.Shift);
            Debug.Assert(deltaLon <= short.MaxValue);
            Debug.Assert(deltaLat <= short.MaxValue);
            Debug.Assert(deltaLon >= short.MinValue);
            Debug.Assert(deltaLat >= short.MinValue);
            writer.Write((short)deltaLon);
            writer.Write((short)deltaLat);
        }
    }
}

